#pragma once

#include <openssl/md5.h>
#include <iostream>
#include <string>
#include <string.h>
#include <unordered_map>
#include <ctime>

#include <jsoncpp/json/json.h>
#include "../comm/httplib.h"
#include "../comm/util.hpp"

namespace ns_session
{
    // namespace session
    using namespace httplib;
    using namespace ns_util;

    class Session
    {
    public:
        Session()
        {
        }
        Session(const std::string &in_json, int id, const std::string &identity)
        {
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);

            _real_str += in_value["user"].asString();
            _real_str += in_value["password"].asString();
            _real_str += identity;
            _real_str += TimeUtil::GetMsTimeStamp();

            _id = id;
            _identity = identity;
        }
        bool SumMd5()
        {
            MD5_CTX ctx;
            // 1.初始化
            MD5_Init(&ctx);

            if (MD5_Update(&ctx, _real_str.c_str(), _real_str.size()) != 1)
            {
                return false;
            }

            unsigned char md5[16] = {0};
            if (MD5_Final(md5, &ctx) != 1)
            {
                return false;
            }

            char tmp[3] = {0};
            char buf[32] = {0};
            for (int i = 0; i < 16; i++)
            {
                snprintf(tmp, sizeof(tmp) - 1, "%02x", md5[i]);
                strncat(buf, tmp, 2);
            }

            _session_id = buf;
            return true;
        }

        //获取会话id
        std::string &GetSessionId()
        {
            SumMd5();
            return _session_id;
        }

    public:
        std::string _session_id; //当前会话的会话id
        std::string _real_str;   //用来生成会话id的原生字符串
        std::string _identity;
        int _id;
    };

    class AllSessionInfo
    {
    public:
        AllSessionInfo()
        {
            pthread_mutex_init(&_map_lock, nullptr);
        }

        ~AllSessionInfo()
        {
            pthread_mutex_destroy(&_map_lock);
        }

        //设置会话信息
        void SetSessionInfo(std::string &session_id, Session &sess)
        {
            pthread_mutex_lock(&_map_lock);
            _session_map.insert(make_pair(session_id, sess));
            pthread_mutex_unlock(&_map_lock);
        }

        //获取查找会话信息的session id
        int GetSessionInfo(const std::string &session_id, Session *session_info)
        {

            pthread_mutex_lock(&_map_lock);
            auto iter = _session_map.find(session_id);
            if (iter == _session_map.end())
            {
                pthread_mutex_unlock(&_map_lock);
                return -1;
            }

            if (session_info != nullptr)
            {
                *session_info = iter->second;
            }
            pthread_mutex_unlock(&_map_lock);
            return 0;
        }
        //判断登录会话ID是正常的还是非法的
        int CheckSessionInfo(const Request &req)
        {
            std::string session_id = GetSessionId(req);
            if (session_id == "")
            {
                return -1;
            }

            Session sess;
            if (GetSessionInfo(session_id, &sess) < 0)
            {
                return -2;
            }

            //如何最终会话校验成功了， 则返回该用户的用户id
            return sess._id;
        }

        //获取会话ID
        std::string GetSessionId(const Request &req)
        {
            std::string session_kv = req.get_header_value("Cookie");

            // JSESSIONID=xxxxx
            // JSESSIONID=
            std::vector<std::string> out;
            //切割字符串
            StringUtil::Spilit(session_kv, out, "=");
            return out.back();
        }

    private:
        std::unordered_map<std::string, Session> _session_map;
        pthread_mutex_t _map_lock;
    };
}